home *** CD-ROM | disk | FTP | other *** search
- ;********************* R-SURF.LSP ******************************************
- ;
- ; Function to create a "rotated surface" from a profile polyline,
- , a center line, and a center point.
- ; The "surface" is created using 3dface entities, and is currently
- ; rotated only about a z-axis. The general case (about any axis)
- ; is left as an exercise.
- ;
- ;
- ; by Simon Jones - Autodesk UK Ltd.
- ; embellished by John Lynch - Autodesk, Inc.
- ; modified by JCG & TK 6/28/87 - Autodesk, Inc.
- ; further modified by Duff Kurland 7/20/87 - Autodesk, Inc.
- ;
- ; This file contains a number of functions, which are called from the main
- ; and other functions. The use of the functions are documented in the
- ; accompanying comments.
- ;
- ; SEMI-GLOBAL VARIABLES:
- ;
- ; cen: center point of surface generation in the x-y plane
- ; lat: Lateral constant for control of segmentation of arc segments
- ; segno: Radial segmentation constant
- ; div: Number of divisions to fill the desired sweep angle
- ; array-deg: Number of degrees for the circular array
- ; v1list: Vertex no. 1 entity list
- ; v2list: Vertex no. 2 entity list
- ; p: profile polyline entity name
- ; cenx: Center point for the array
- ; cx: x-coordinate of the start point of the center line
- ; cy: y-coordinate of the start point of the center line
- ; minrad: dist from the center line to the last point on the profile
- ; maxrad: dist from the center line to the current point on the profile
- ; elev: current incremental elevation
- ; h: vertical increment from last to current point on profile
- ; cflag: closed polyline flag
-
-
- ; Construct a single 3DFACE segment
-
- (defun dseg ( / pt1 pt2 pt3 pt4)
- (setq pt1 (polar cen 0 minrad))
- (setq pt2 (polar cen 0 maxrad))
- (setq pt3 (polar cen div maxrad))
- (setq pt4 (polar cen div minrad))
- (command "3DFACE"
- (list (car pt1) (cadr pt1) (+ elev h))
- (list (car pt2) (cadr pt2) elev )
- (list (car pt3) (cadr pt3) elev )
- (list (car pt4) (cadr pt4) (+ elev h))
- )
- (command "")
- )
-
- ; Function to handle a linear segment of a polyline
-
- (defun linseg()
- (setq maxrad (- (car cenx) (cadr (assoc 10 v1list))))
- (setq minrad (- (car cenx) (cadr (assoc 10 v2list))))
- (setq h (- (caddr (assoc 10 v2list))
- (caddr (assoc 10 v1list))
- )
- )
- (dseg)
- (setq elev (+ elev h)) ; reset the elevation for next seg
- )
-
- ; Function to handle a polyline arc segment.
- ;
- ; s : Starting point
- ; e : Ending point
- ; b : Bulge of arc
- ;
- ; Calculate the included angle, midpoint between vertices,
- ; and the directional angle from the starting to ending vertex
-
- (defun arcseg (s e b / iang mpt dang cpt rad mpt nseg bpt ept dd )
- (setq iang (* 4.0 (atan (abs b)))
- mpt (midpt s e)
- dang (angle s e)
- )
-
- ; find the center and radius of the arc
- (if (< (abs b) 1) ; if the bulge is > 1
- (progn ; use the complementary arc
- (setq rad (/ (/ (distance s e) 2.0) (sin (/ iang 2.0)))
- m (* rad (cos (/ iang 2.0)))
- )
- (if (< b 0) ; clockwise or counterclockwise?
- (setq cpt (polar mpt (- dang (/ pi 2.0)) m))
- (setq cpt (polar mpt (+ dang (/ pi 2.0)) m))
- )
- ) ; end of progn
- (progn ; otherwise ...
- (setq rad (/ (/ (distance s e) 2.0) (sin (- pi (/ iang 2.0))))
- m (* rad (cos (- pi (/ iang 2.0))))
- )
- (if (< b 0)
- (setq cpt (polar mpt (+ dang (/ pi 2.0)) m))
- (setq cpt (polar mpt (- dang (/ pi 2.0)) m))
- )
- ) ; end of progn
- ) ; end of if
-
- (if (< b 0)
- (setq iang (- 0.0 iang)) ; negative bulge means clockwise arc
- )
-
- ; Set the number of segments according to the value of "lat" (global)
- (setq nseg lat
- dd (/ iang (+ nseg 1)) ; delta angle based on nseg
- bpt s ; initialize start point to start of arc
- cnt 0 ; initialize count to 0
- )
-
- (while (< cnt nseg)
- (setq ept (polar cpt (+ (angle cpt bpt) dd) rad) ; end of this segment
- maxrad (- (car cenx) (car bpt))
- minrad (- (car cenx) (car ept))
- h (- (cadr ept) (cadr bpt))
- )
- (dseg)
-
- ; Reset the starting point and increment cnt and elev
- (setq bpt ept
- cnt (1+ cnt)
- elev (+ elev h)
- )
- )
-
- ; Do the last segment, which ends on the endpoint of the arc
- (setq ept e
- maxrad (- (car cenx) (car bpt))
- minrad (- (car cenx) (car ept))
- h (- (cadr ept) (cadr bpt))
- )
- (dseg)
- (setq elev (+ elev h)) ; Reset elev
- )
-
- ; Function to calculate and return the midpoint between two points.
-
- (defun midpt(p1 p2 / x1 x2 y1 y2)
- (setq x1 (car p1)
- y1 (cadr p1)
- x2 (car p2)
- y2 (cadr p2)
- )
- (list (/ (+ x1 x2) 2.0) (/ (+ y1 y2) 2.0))
- )
-
- ; Convert Degrees to Radians
-
- (defun dtr (a)
- (* pi (/ a 180.0))
- )
-
- ; Convert Radians to Degrees
-
- (defun rtd (a)
- (/ (* a 180.0) pi)
- )
-
- ; Save the SETVARs specified in the mode list into the global MLST.
- ; The specified modes must not be read only. i.e. "CLAYER" should
- ; not be included in the list.
-
- (defun MODES (a)
- (setq MLST '())
- (repeat (length a)
- (setq MLST (append MLST (list (list (car a) (getvar (car a))))))
- (setq a (cdr a)))
- )
-
- ; Restore the SETVARs specified in the global MLST.
-
- (defun MODER ()
- (repeat (length MLST)
- (setvar (caar MLST) (cadar MLST))
- (setq MLST (cdr MLST))
- )
- )
-
- ; Function to select the center line of the profile
-
- (defun c-line ( / cline clist loop)
- (setq loop T)
- (while loop
- (setq cline (entsel "\nSelect center line: "))
- (if (null (car cline))
- (progn
- (prompt " 1 selected, 0 found.")
- (setq clist '( '(0 . "JUNK"))) ; dummy assoc list for following
- ; test of entity
- )
- (setq clist (entget (car cline)))
- )
- (if (= (cdr (assoc 0 clist)) "LINE")
- (setq loop nil) ; all tests pass - exit loop
- (prompt " Entity selected is not a line.")
- )
- )
- (setq cx (cadr (assoc 10 clist)) ; global variables for x & y coord
- cy (caddr (assoc 10 clist)) ; of start point of center line
- )
- )
-
- ; Function to select the profile for the surface
-
- (defun prosel ( / plist loop)
- (setq cflag nil
- loop T
- )
- (while loop
- (setq p (entsel "\nSelect Profile: ")) ; global variable for use in
- ; main program
- (if (null (car p))
- (progn
- (prompt " 1 selected, 0 found.")
- (setq plist '( '(0 . "JUNK"))) ; dummy assoc list for following
- ; test of entity
- )
- (setq plist (entget (car p)))
- )
- (if (= (cdr (assoc 0 plist)) "POLYLINE")
- (setq loop nil) ; all tests pass - exit loop
- (prompt " Entity selected is not a polyline.")
- )
- )
- (if (= (logand (cdr (assoc 70 plist)) 1) 1)
- (setq cflag 1)
- )
- )
-
- ; Get next polyline vertex, ignoring spline control points
-
- (defun vertnext (curr / v ve)
- (setq ve (entget (setq v (entnext curr))))
- (while (and (= (cdr (assoc 0 ve)) "VERTEX")
- (= (logand (cdr (assoc 70 ve)) 16) 16))
- (setq ve (entget (setq v (entnext v))))
- )
- v
- )
-
- ; Error handler
-
- (defun myerror (st) ; Handle cleanup on CTRL-C
- (moder)
- (terpri)
- (princ (strcat "\nerror: " st "\n"))
- (setq *error* olderr)
- (princ)
- )
-
- ; MAIN PROGRAM
-
- (defun C:R-SURF ( / array-deg bulge cen cenx cflag cx cy c1 c1list
- deg div e elev h lat maxrad minrad olderr p s segno
- v1 v1list v2 v2list)
-
- (setq olderr *error* ; Establish our error handler
- *error* myerror)
-
- ; Store the system variables changed during the function
-
- (modes '("ELEVATION" "THICKNESS" "CMDECHO" "BLIPMODE" "HIGHLIGHT"))
- (setvar "CMDECHO" 0)
- (setvar "HIGHLIGHT" 0)
-
- (prosel) ; Select the profile for the rotated surface
- (c-line) ; Select the center line of the profile
-
- ; Select the center point for the construction of the surface (cen)
-
- (initget (+ 1 16)) ; 3D point, cannot be null
- (setq cen (getpoint "\nCenter point for construction: "))
-
- ; Enter the sweep angle of the surface (deg)
-
- (setq deg (getangle cen "\nDegrees of rotation <360>: "))
- (if (null deg)
- (setq deg 360.0)
- (setq deg (rtd deg))
- )
-
- ; Enter the constant to control arc segmentation (lat)
-
- (initget (+ 2 4)) ; No negative or zero values
- (setq lat (getint "\nArc segment constant <10>: "))
- (if (null lat)
- (setq lat 10)
- )
-
- ; Enter value to control radial segmentation (segno)
-
- (initget (+ 2 4)) ; No negative or zero values
- (setq segno (getint "\nRadial segment constant <15>: "))
- (if (null segno)
- (setq segno 15)
- )
-
- ; Set up the number of divisions from the sweep angle
-
- (setq div (/ deg segno))
- (setq array-deg (- deg div))
- (setq div (dtr div))
-
- (setvar "BLIPMODE" 0)
-
- ; Set the vertices and retrieve vertex data
-
- (setq v1list (entget (setq v1 (vertnext (car p)))))
- (setq v2list (entget (setq v2 (vertnext v1))))
-
- ; Set the closing vertex equal to the starting vertex (c1)
-
- (setq c1 v1
- c1list v1list
- )
-
- ; Set the center point for the array from the center line value
-
- (setq cenx (list cx (caddr (assoc 10 v1list))))
-
- ; Set the starting elevation to the center point's Z, plus the Y
- ; coordinate of the first vertex relative to the start of the center line
-
- (setq elev (+ (caddr cen)
- (- (caddr (assoc 10 v1list)) cy)
- )
- )
-
- ; Create a selection set and save the current last entity
-
- (setq s (ssadd)
- e (entlast)
- )
-
- ; Process the vertices of the polyline ...
-
- (while (= (cdr (assoc 0 v2list)) "VERTEX")
- (setq bulge (cdr (assoc 42 v1list)))
- (if (= bulge 0)
- (linseg)
- (arcseg (cdr (assoc 10 v1list)) (cdr (assoc 10 v2list)) bulge)
- )
-
- ; Reset the vertex lists for the next segment
-
- (setq v1 v2
- v1list v2list
- v2 (vertnext v1)
- v2list (entget v2)
- )
- )
-
- ; Test for a closed polyline
-
- (if (= cflag 1)
- (progn
- (setq v2 c1
- v2list c1list
- )
- (linseg) ; Draw the closing linear segment
- )
- )
-
- ; add all entities into the selection set
-
- (while (setq e (entnext e))
- (ssadd e s)
- )
-
- ; array all the entities
-
- (command "ARRAY" S "" "P" cen segno array-deg "")
- (moder) ; Reset the system variables
- (setq *error* olderr)
- (princ)
- )
-